home *** CD-ROM | disk | FTP | other *** search
- *** orig/gdb-4.12/gdb/go32targ.c Tue Jul 26 01:10:40 1994
- --- src/gdb-4.12/gdb/go32targ.c Wed Jul 27 02:03:38 1994
- ***************
- *** 0 ****
- --- 1,484 ----
- + /* Target-vector operations for controlling go32 processes, for GDB.
- + Copyright 1994 Free Software Foundation, Inc.
- + Contributed by DJ Delorie.
- +
- + This file is part of GDB.
- +
- + This program is free software; you can redistribute it and/or modify
- + it under the terms of the GNU General Public License as published by
- + the Free Software Foundation; either version 2 of the License, or
- + (at your option) any later version.
- +
- + This program is distributed in the hope that it will be useful,
- + but WITHOUT ANY WARRANTY; without even the implied warranty of
- + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- + GNU General Public License for more details.
- +
- + You should have received a copy of the GNU General Public License
- + along with this program; if not, write to the Free Software
- + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
- +
- + #include "defs.h"
- + #include "frame.h" /* required by inferior.h */
- + #include "inferior.h"
- + #include "target.h"
- + #include "wait.h"
- + #include "gdbcore.h"
- + #include "command.h"
- + #include <signal.h>
- +
- + extern char **environ;
- +
- + /* Forward declaration */
- + extern struct target_ops go32_ops;
- +
- + /* ╔════════════════════════════════════════════════════════════════════════════╗
- + ║ Go32's external debugger interface routines ║
- + ╚════════════════════════════════════════════════════════════════════════════╝ */
- +
- + #define SOME_PID 42
- +
- + int prog_has_started = 0;
- +
- + #include <sys/farptr.h>
- + #define far
- + #include <../go32/gotypes.h> /* from go32 sources */
- + #include <../go32/tss.h>
- + #include <../go32/extdebug.h>
- + #include <../go32/paging.h>
- +
- + static ExternalDebuggerInfo edi;
- + static TSS a_tss;
- + static AREAS areas[MAX_AREA];
- +
- + static int my_ds;
- + static int app_ds;
- + static int edi_seg;
- + static int edi_ofs;
- +
- + #define r_ofs(x) ((int)(&(((TSS *)0)->x)))
- + static struct {
- + int tss_ofs;
- + int size;
- + } regno_mapping[] = {
- + r_ofs(tss_eax), 4,
- + r_ofs(tss_ecx), 4,
- + r_ofs(tss_edx), 4,
- + r_ofs(tss_ebx), 4,
- + r_ofs(tss_esp), 4,
- + r_ofs(tss_ebp), 4,
- + r_ofs(tss_esi), 4,
- + r_ofs(tss_edi), 4,
- + r_ofs(tss_eip), 4,
- + r_ofs(tss_eflags), 4,
- + r_ofs(tss_cs), 2,
- + r_ofs(tss_ss), 2,
- + r_ofs(tss_ds), 2,
- + r_ofs(tss_es), 2,
- + r_ofs(tss_fs), 2,
- + r_ofs(tss_gs), 2
- + };
- +
- + static struct {
- + int go32_sig;
- + int gdb_sig;
- + } sig_map[] = {
- + 0, TARGET_SIGNAL_BUS,
- + 1, TARGET_SIGNAL_TRAP,
- + 2, TARGET_SIGNAL_UNKNOWN,
- + 3, TARGET_SIGNAL_TRAP,
- + 4, TARGET_SIGNAL_FPE,
- + 5, TARGET_SIGNAL_SEGV,
- + 6, TARGET_SIGNAL_ILL,
- + 7, TARGET_SIGNAL_FPE,
- + 8, TARGET_SIGNAL_BUS,
- + 9, TARGET_SIGNAL_FPE,
- + 10, TARGET_SIGNAL_BUS,
- + 11, TARGET_SIGNAL_SEGV,
- + 12, TARGET_SIGNAL_SEGV,
- + 13, TARGET_SIGNAL_SEGV,
- + 14, TARGET_SIGNAL_SEGV,
- + 16, TARGET_SIGNAL_FPE,
- + 31, TARGET_SIGNAL_ILL,
- + -1,-1
- + };
- +
- + static void go32_edi_init()
- + {
- + int i;
- + asm("movw $0xfe01,%ax");
- + asm("int $0x21");
- + asm("movl %edx,_edi_seg");
- + asm("movl %eax,_edi_ofs");
- + asm("xor %eax,%eax");
- + asm("movw %ds,%ax");
- + asm("movl %eax,_my_ds");
- + movedata(edi_seg, edi_ofs, my_ds, (int)(&edi), sizeof(edi));
- + movedata(edi.a_tss_seg, edi.a_tss_ofs, my_ds, (int)(&a_tss), sizeof(TSS));
- + app_ds = a_tss.tss_ds;
- + movedata(edi.areas_seg, edi.areas_ofs, my_ds, (int)areas, sizeof(areas));
- + for (i=0; i<MAX_AREA; i++)
- + {
- + areas[i].first_addr -= edi.app_base;
- + areas[i].last_addr -= edi.app_base;
- + }
- + }
- +
- + static void go32_edi_run_child(void)
- + {
- + int i;
- + prog_has_started = 1;
- +
- + movedata(my_ds, (int)(&edi), edi_seg, edi_ofs, sizeof(edi));
- + movedata(my_ds, (int)(&a_tss), edi.a_tss_seg, edi.a_tss_ofs, sizeof(TSS));
- + asm("movw $0xfe00,%ax");
- + asm("int $0x21");
- + movedata(edi_seg, edi_ofs, my_ds, (int)(&edi), sizeof(edi));
- + movedata(edi.a_tss_seg, edi.a_tss_ofs, my_ds, (int)(&a_tss), sizeof(TSS));
- +
- + movedata(edi.areas_seg, edi.areas_ofs, my_ds, (int)areas, sizeof(areas));
- + for (i=0; i<MAX_AREA; i++)
- + {
- + areas[i].first_addr -= edi.app_base;
- + areas[i].last_addr -= edi.app_base;
- + }
- + }
- +
- + static int invalid_addr(word32 a, unsigned len)
- + {
- + int i;
- + if ((int)invalid_addr > 0)
- + return 0;
- + for (i=0; i<MAX_AREA; i++)
- + if (a>=areas[i].first_addr && (a+len-1) <= areas[i].last_addr)
- + return 0;
- + return 1;
- + }
- +
- + static int go32_edi_read_child(word32 child_addr, void *buf, unsigned len)
- + {
- + if (invalid_addr(child_addr, len))
- + return 0;
- + movedata(app_ds, child_addr, my_ds, (int)buf, len);
- + return 0;
- + }
- +
- + static int go32_edi_write_child(word32 child_addr, void *buf, unsigned len)
- + {
- + if (invalid_addr(child_addr, len))
- + return 0;
- + movedata(my_ds, (int)buf, app_ds, child_addr, len);
- + return 0;
- + }
- +
- + static char *new_argv[3] = {
- + "gdb",
- + 0,
- + 0
- + };
- +
- + void
- + init_go32_extdebug(int *argc, char ***argv)
- + {
- + char *fn;
- + int i, v;
- + int tenvp;
- +
- + go32_edi_init();
- +
- + fn = (char *)malloc(edi.filename_len + 1);
- + movedata(edi.filename_seg, edi.filename_ofs, my_ds, (int)(fn), edi.filename_len+1);
- +
- + #if 0
- + printf("filename: %s\n", fn);
- +
- + printf("text: %#08x - %#08x\n", areas[A_text].first_addr, areas[A_text].last_addr);
- + printf("data: %#08x - %#08x\n", areas[A_data].first_addr, areas[A_data].last_addr);
- + printf("bss: %#08x - %#08x\n", areas[A_bss].first_addr, areas[A_bss].last_addr);
- +
- + printf("stack: %#x\n", a_tss.tss_esp);
- + #endif
- +
- + go32_edi_read_child(a_tss.tss_esp+8, &tenvp, 4);
- +
- + new_argv[1] = fn;
- +
- + for (i=0; ; i++)
- + {
- + int ep;
- + char *s;
- + go32_edi_read_child(tenvp+i*4, &ep, 4);
- + if (!ep)
- + break;
- + }
- + environ = (char **)malloc((i+1) * sizeof(char *));
- +
- + for (i=0; ; i++)
- + {
- + int ep;
- + char *s;
- + go32_edi_read_child(tenvp+i*4, &ep, 4);
- + if (!ep)
- + {
- + environ[i] = 0;
- + break;
- + }
- + _farsetsel(app_ds);
- + for (v=0; _farnspeekb(ep+v); v++);
- + environ[i] = (char *)malloc(v+1);
- + go32_edi_read_child(ep, environ[i], v+1);
- + }
- +
- + *argc = 2;
- + *argv = new_argv;
- + }
- +
- + /* ───────────────────────────────────────────────────────────────────────────── */
- +
- + /* special sbrk that uses local heap and zeros memory. */
- + void *
- + sbrk(int l)
- + {
- + extern int end;
- + static int sold = (int)&end;
- + memset(sold, 0, l);
- + sold += l;
- + return (void *)(sold-l);
- + }
- +
- + /* ═════════════════════════════════════════════════════════════════════════════ */
- +
- + static void
- + go32_open(char *name, int from_tty)
- + {
- + printf("Use the `run' command to run go32 programs\n");
- + }
- +
- + /* ───────────────────────────────────────────────────────────────────────────── */
- +
- + static void go32_close(int quitting)
- + {
- + }
- +
- + /* ───────────────────────────────────────────────────────────────────────────── */
- +
- + static void
- + go32_attach(char *args, int from_tty)
- + {
- + printf("Use the `run' command to run go32 programs\n");
- + }
- +
- + /* ───────────────────────────────────────────────────────────────────────────── */
- +
- + static void
- + go32_detach(char *args, int from_tty)
- + {
- + }
- +
- + /* ───────────────────────────────────────────────────────────────────────────── */
- +
- + static int resume_is_step;
- +
- + static void
- + go32_resume(int pid, int step, enum target_signal siggnal)
- + {
- + resume_is_step = step;
- + }
- +
- + /* ───────────────────────────────────────────────────────────────────────────── */
- +
- + static int
- + go32_wait(int pid, struct target_waitstatus *status)
- + {
- + /* printf("go32_wait %d\n", pid); */
- + if (resume_is_step)
- + a_tss.tss_eflags |= 0x0100;
- + else
- + a_tss.tss_eflags &= 0xfeff;
- + go32_edi_run_child();
- + if (a_tss.tss_irqn == 0x21)
- + {
- + status->kind = TARGET_WAITKIND_EXITED;
- + status->value.integer = a_tss.tss_eax & 0xff;
- + }
- + else
- + {
- + int i;
- + status->value.sig = TARGET_SIGNAL_UNKNOWN;
- + for (i=0; sig_map[i].go32_sig != -1; i++)
- + if (a_tss.tss_irqn == sig_map[i].go32_sig)
- + {
- + status->value.sig = sig_map[i].gdb_sig;
- + break;
- + }
- + status->kind = TARGET_WAITKIND_STOPPED;
- + }
- + return SOME_PID;
- + }
- +
- + /* ───────────────────────────────────────────────────────────────────────────── */
- +
- + static void
- + go32_fetch_registers(int regno)
- + {
- + if (regno >= 0)
- + supply_register(regno, (char *)&a_tss + regno_mapping[regno].tss_ofs);
- + else
- + {
- + int r;
- + for (r=0; r<sizeof(regno_mapping)/sizeof(regno_mapping[0]); r++)
- + supply_register(r, (char *)&a_tss + regno_mapping[r].tss_ofs);
- + }
- + }
- +
- + /* ───────────────────────────────────────────────────────────────────────────── */
- +
- + static void store_register(int regno)
- + {
- + char *rp = (char *)&a_tss + regno_mapping[regno].tss_ofs;
- + int v = *(int *)(®isters[REGISTER_BYTE(regno)]);
- + switch (regno_mapping[regno].size)
- + {
- + case 4:
- + *(int *)rp = v;
- + break;
- + case 2:
- + *(short *)rp = v;
- + break;
- + }
- + }
- +
- + static void
- + go32_store_registers(int regno)
- + {
- + if (regno >= 0)
- + store_register(regno);
- + else
- + {
- + int r;
- + for (r=0; r<sizeof(regno_mapping)/sizeof(regno_mapping[0]); r++)
- + store_register(regno);
- + }
- + }
- +
- + /* ───────────────────────────────────────────────────────────────────────────── */
- +
- + static void
- + go32_prepare_to_store(void)
- + {
- + }
- +
- + /* ───────────────────────────────────────────────────────────────────────────── */
- +
- + static int
- + go32_xfer_memory(CORE_ADDR memaddr, char *myaddr, int len, int write,
- + struct target_ops *target)
- + {
- + /* printf("go32_xfer_memory %x %x %d %d\n", memaddr, myaddr, len, write); */
- + if (write)
- + go32_edi_write_child(memaddr, myaddr, len);
- + else
- + go32_edi_read_child(memaddr, myaddr, len);
- + return len;
- + }
- +
- + /* ───────────────────────────────────────────────────────────────────────────── */
- +
- + static void
- + go32_files_info(struct target_ops *target)
- + {
- + printf_filtered("You are running a go32 program called `%s'\n", new_argv[1]);
- + }
- +
- + /* ───────────────────────────────────────────────────────────────────────────── */
- +
- + static void
- + go32_kill_inferior(void)
- + {
- + /* nothing to do */
- + }
- +
- + /* ───────────────────────────────────────────────────────────────────────────── */
- +
- + static void
- + go32_create_inferior(char *exec_file, char *args, char **env)
- + {
- + if (prog_has_started)
- + {
- + printf("The program has been started once already. Please quit and restart gdb.\n");
- + return;
- + }
- + inferior_pid = SOME_PID;
- + push_target(&go32_ops);
- + clear_proceed_status();
- + proceed((CORE_ADDR) -1, TARGET_SIGNAL_0, 0);
- + }
- +
- + /* ───────────────────────────────────────────────────────────────────────────── */
- +
- + static void
- + go32_mourn_inferior(void)
- + {
- + unpush_target(&go32_ops);
- + }
- +
- + /* ───────────────────────────────────────────────────────────────────────────── */
- +
- + static int go32_can_run(void)
- + {
- + return 1;
- + }
- +
- + /* ───────────────────────────────────────────────────────────────────────────── */
- +
- + static void ignore(void) {}
- + static void ignore2(char *a,int b) {}
- +
- + /* ═════════════════════════════════════════════════════════════════════════════ */
- +
- + struct target_ops go32_ops = {
- + "go32", /* to_shortname */
- + "go32 target process", /* to_longname */
- + "Program loaded by go32, when gdb is used as an external debugger", /* to_doc */
- + go32_open, /* to_open */
- + go32_close, /* to_close */
- + go32_attach, /* to_attach */
- + go32_detach, /* to_detach */
- + go32_resume, /* to_resume */
- + go32_wait, /* to_wait */
- + go32_fetch_registers, /* to_fetch_registers */
- + go32_store_registers, /* to_store_registers */
- + go32_prepare_to_store, /* to_prepare_to_store */
- + go32_xfer_memory, /* to_xfer_memory */
- + go32_files_info, /* to_files_info */
- + memory_insert_breakpoint, /* to_insert_breakpoint */
- + memory_remove_breakpoint, /* to_remove_breakpoint */
- + ignore, /* to_terminal_init */
- + ignore, /* to_terminal_inferior */
- + ignore, /* to_terminal_ours_for_output */
- + ignore, /* to_terminal_ours */
- + ignore2, /* to_terminal_info */
- + go32_kill_inferior, /* to_kill */
- + 0, /* to_load */
- + 0, /* to_lookup_symbol */
- + go32_create_inferior, /* to_create_inferior */
- + go32_mourn_inferior, /* to_mourn_inferior */
- + go32_can_run, /* to_can_run */
- + 0, /* to_notice_signals */
- + process_stratum, /* to_stratum */
- + 0, /* to_next */
- + 1, /* to_has_all_memory */
- + 1, /* to_has_memory */
- + 1, /* to_has_stack */
- + 1, /* to_has_registers */
- + 1, /* to_has_execution */
- + 0, /* sections */
- + 0, /* sections_end */
- + OPS_MAGIC /* to_magic */
- + };
- +
- + void
- + _initialize_inftarg ()
- + {
- + add_target (&go32_ops);
- + }
-